#include <QtGui>
#include <iostream>
#include <fstream>
#include <string>

#include "testDialog.h"
#include "dialog.h"
#include "register.h"
#include "group.h"
#include "mainwindow.h"

#define REG_SIZE 32


/** TestDialog constructor.*/
TestDialog::TestDialog(MainWindow *big)
    : QWidget()
{

bigWindow=big;
    createEditingArea();
    createListArea();


   mainLayout = new QGridLayout;

   mainLayout->addWidget(genTestFile,0,0);
mainLayout->addWidget(autoGenButton,0,1);
    mainLayout->addWidget(operationType,1,0);
    mainLayout->addWidget(regs,1,1);
    mainLayout->addWidget(fields,1,2);
    mainLayout->addWidget(valueLabel,1,3);
    mainLayout->addWidget(value,1,4);
    mainLayout->addWidget(sec,1,5);
    mainLayout->addWidget(addTestButton,1,6);

    mainLayout->addWidget(delTestButton,2,6,Qt::AlignTop);
    mainLayout->addWidget(testListWidget,2,0,1,6);

    setLayout(mainLayout);

    layoutModified=false;


}

void TestDialog::updateComboBox(){
    QQueue<Register *>* regQueue = bigWindow->getDialog()->getRegisters();


    if(layoutModified==true && testListWidget->topLevelItemCount()>0 )
        QMessageBox::warning(this, tr("drvAutogen"),
                                           tr("The layout has changed since your last test creation.\nThe tests already created might be inconsistent."),
                                           QMessageBox::Ok);

    layoutModified=false;

fields->clear();
regs->clear();
 regs->addItem("-");
  //fields->addItem("-");
    for(int i=0;i<regQueue->size();i++){
         regs->addItem(regQueue->at(i)->title());
//      for(int j=0;j<regQueue->at(i)->getTabs()->count();j++){
//
//          fields->addItem(regQueue->at(i)->getTabs()->tabText(j));
//
//      }

    }
}

void TestDialog::updateFieldCombo(int i){
QQueue<Register *>* regQueue = bigWindow->getDialog()->getRegisters();
if(i>0){
    fields->clear();
    fields->addItem("-");
    for(int j=0;j<regQueue->at(i-1)->getTabs()->count();j++){

              fields->addItem(regQueue->at(i-1)->getTabs()->tabText(j));

          }
}else
{fields->clear();
fields->addItem("-");
}


}


void TestDialog::createEditingArea(){


    genTestFile = new QPushButton("Generate Test File");
    connect(genTestFile,SIGNAL(pressed()), this, SLOT(generateTestFile()));

    autoGenButton = new QPushButton("Auto-generate Tests");
    connect(autoGenButton,SIGNAL(pressed()), this, SLOT(autoGenerate()));

    operationType = new QComboBox();
    operationType->addItem("Read");
    operationType->addItem("Write");
    operationType->addItem("ReadWrite");

    regs = new QComboBox();
    regs->addItem("-");
    regs->setMinimumWidth(130);

    connect(regs,SIGNAL(currentIndexChanged(int)), this, SLOT(updateFieldCombo(int)));


    fields = new QComboBox();
    //fields->addItem("-");
    fields->setMinimumWidth(120);





    valueLabel = new QLabel("Value:");
    value =  new QLineEdit();
    value->setMaximumWidth(200);
    value->setMaxLength(10);
    value->setValidator(new QRegExpValidator(QRegExp("(0x)?[A-F|a-f|0-9]{0,8}"),this));

    sec =  new QSpinBox();
    sec->setSuffix(" ns");

    addTestButton= new QPushButton(QIcon::fromTheme("list-add"),"Add Test");
    addTestButton->setMaximumWidth(200);
    connect(addTestButton,SIGNAL(pressed()), this, SLOT(addTestCase()));



    delTestButton= new QPushButton(QIcon::fromTheme("window-close"),"Delete Item");
    delTestButton->setMaximumWidth(200);
    connect(delTestButton,SIGNAL(pressed()), this, SLOT(delTestCase()));


}
void TestDialog::createListArea(){

testListWidget = new QTreeWidget();

testListWidget->setColumnCount(6);
testListWidget->setColumnWidth(0,100);
testListWidget->setColumnWidth(1,100);
testListWidget->setColumnWidth(2,100);
testListWidget->setColumnWidth(3,100);
testListWidget->setColumnWidth(4,100);
testListWidget->setColumnWidth(5,40);
QStringList strings;
strings <<"Type"<<"Register"<<"Field"<<"Address"<<"Value"<<"Time";
testListWidget->setHeaderLabels(strings);




}


void TestDialog::autoGenerate(){}

void TestDialog::addTestCase(){

    //if qualcosa manca, non generare.
    if(regs->currentIndex()==0){return;}


    QStringList strings;
    strings << operationType->currentText();
    strings << regs->currentText();
    strings << fields->currentText();
    strings << QString::number(bigWindow->getDialog()->getRegisters()->at(regs->currentIndex()-1)->getCurrentOffset().toInt() + bigWindow->getDialog()->getBaseAddr().toInt(0,16),16).rightJustified(8,'0');

    QString x(value->text());
    x=x.rightJustified(8,'0');


    //QString y=QString::number(x.toInt(0,16),2).rightJustified(32,'0',true);
    QString y=QString::number(0).rightJustified(32,'0',true);

    //    strings<<y;
    if(fields->currentIndex()==0)
        strings<<x;
    else{

        //>> this method had troubles with large numbers (e.g. 0x FFFFFFFF ).
//        if(bigWindow->getDialog()->getRegisters()->at(regs->currentIndex()-1)->getNotation()==Qt::RightToLeft)
//            {for(int j=0;j<y.length();j++)
//                if(j<bigWindow->getDialog()->getRegisters()->at(regs->currentIndex()-1)->getGroups()->at(fields->currentIndex()-1)->getLowerBit()->value() || j>bigWindow->getDialog()->getRegisters()->at(regs->currentIndex()-1)->getGroups()->at(fields->currentIndex()-1)->getUpperBit()->value())
//                    y.replace(31-j,1,"0");}
//        else
//                    { for(int j=0;j<y.length();j++)
//                if(j<bigWindow->getDialog()->getRegisters()->at(regs->currentIndex()-1)->getGroups()->at(fields->currentIndex()-1)->getLowerBit()->value() || j>bigWindow->getDialog()->getRegisters()->at(regs->currentIndex()-1)->getGroups()->at(fields->currentIndex()-1)->getUpperBit()->value())
//                    y.replace(j,1,"0");}
//
//        strings<<QString::number(y.toInt(0,2),16).rightJustified(8,'0');

        for(int j=0;j<y.length();j++)
            if(j>=bigWindow->getDialog()->getRegisters()->at(regs->currentIndex()-1)->getGroups()->at(fields->currentIndex()-1)->getLowerBit()->value() && j<=bigWindow->getDialog()->getRegisters()->at(regs->currentIndex()-1)->getGroups()->at(fields->currentIndex()-1)->getUpperBit()->value())
            {
            int k;
            if(bigWindow->getDialog()->getRegisters()->at(regs->currentIndex()-1)->getNotation()==Qt::RightToLeft)
                k = 31-j;
            else
                k=j;

            int m = k/4; //posizione della cifra all'interno dell'hex
            int n = k%4; //posizione del bit all'interno dei 4 bit
            
                QString u(x.at(m));
                QString z = QString::number(u.toInt(0,16),2).rightJustified(4,'0',true);
                if(z.at(n).digitValue()==1)
                    y.replace(k,1,"1");
            
        
                }

        QString y1=y.mid(0,16);
        QString y2=y.mid(16,16);

        

        y1=QString::number(y1.toInt(0,2),16).rightJustified(4,'0');
        y2=QString::number(y2.toInt(0,2),16).rightJustified(4,'0');
        
        strings<<y1.append(y2);

    }



    strings << QString::number(sec->value());
    QTreeWidgetItem* item;
    item= new QTreeWidgetItem(testListWidget,strings);

//    testListWidget->resizeColumnToContents(0);
//    testListWidget->resizeColumnToContents(1);
//    testListWidget->resizeColumnToContents(2);
//    testListWidget->resizeColumnToContents(3);
//    testListWidget->resizeColumnToContents(4);


    regs->setCurrentIndex(0);
    value->clear();
    sec->setValue(0);



}

void TestDialog::delTestCase(){

if(testListWidget->topLevelItemCount()<=0 || testListWidget->currentItem()==NULL)
    {
//    QMessageBox::warning(this, tr("drvAutogen"),
//                                   tr("There is nothing to delete. Select a row first."),
//                                   QMessageBox::Ok);
}
else{

    QMessageBox::StandardButton ret;
    ret = QMessageBox::warning(this, tr("drvAutogen"),
                               tr("Do you want to delete this test?"),
                               QMessageBox::Yes | QMessageBox::Cancel);
    if (ret == QMessageBox::Yes)
    {
      testListWidget->takeTopLevelItem(testListWidget->indexOfTopLevelItem(testListWidget->currentItem()));


        }

}

}



void TestDialog::generateTestFile(){

     QString fileName = QFileDialog::getSaveFileName(this);
        if (fileName.isEmpty())
            return;

        QFile file(fileName);
        if (!file.open(QFile::WriteOnly | QFile::Text)) {
            QMessageBox::warning(this, tr("drvAutogen"),
                                 tr("Cannot write file %1:\n%2.")
                                 .arg(fileName)
                                 .arg(file.errorString()));
            return;
        }

    QTextStream out(&file);

    for(int i=0;i<testListWidget->topLevelItemCount();i++){

        if(testListWidget->topLevelItem(i)->text(0)=="Read")
            out<<"0";
        else if(testListWidget->topLevelItem(i)->text(0)=="Write")
            out<<"1";
        else
            out<<"2";

        out<<" "<<testListWidget->topLevelItem(i)->text(3);
        out<<" "<<testListWidget->topLevelItem(i)->text(4);
        out<<" "<<testListWidget->topLevelItem(i)->text(5)<<" ns";
        out<<"\n";



    }



        bigWindow->statusBar()->showMessage(tr("Test file saved"), 2000);


}





//! The content has been modified
void TestDialog::hasChanged(){
    layoutModified=true;

}



